package alfred.mdp.tsp.client;

import alfred.mdp.client.Client;
import alfred.mdp.tsp.Titanic;
import org.zeromq.ZContext;
import org.zeromq.ZDispatcher;
import org.zeromq.ZFrame;
import org.zeromq.ZMsg;

import java.util.concurrent.TimeUnit;

import static alfred.mdp.messages.ProtocolMessage.get;
import static alfred.mdp.messages.ProtocolMessage.getSubMsg;
import static alfred.mdp.utils.Utils.asByteArray;
import static alfred.mdp.utils.Utils.asString;

/**
 */
public class TitanicClient {

    private final Client majordomoClient;

    public TitanicClient(ZContext context, ZDispatcher dispatcher, String clientsEndpoint) {
        this.majordomoClient = new Client(context, dispatcher, clientsEndpoint);
    }

    public String request(String serviceName, ZMsg message, TimeUnit unit, long value) {
        ZMsg titanicRequestMessage = new ZMsg();
        titanicRequestMessage.addLast(asByteArray(serviceName));
        titanicRequestMessage.addAll(message);
        ZMsg response = majordomoClient.request(Titanic.TITANIC_REQUEST_SERVICE, titanicRequestMessage, unit, value);
        ZFrame responseCode = get(response, 0);
        if (Titanic.ResponseCode.OK.equals(responseCode)) {
            return asString(get(response, 1).getData());

        } else if (Titanic.ResponseCode.UNKNOWN.equals(responseCode)) {
            //impossible case
            throw new IllegalStateException("Grave error");

        } else if (Titanic.ResponseCode.ERROR.equals(responseCode)) {
            throw new IllegalStateException("Error during connect to broker");

        } else {
            throw new IllegalStateException("Unknown response code:" + responseCode + asString(get(response, 0).getData()));

        }
    }


    public ZMsg reply(String uuid, TimeUnit unit, long value) {
        ZMsg titanicReplyMessage = new ZMsg();
        titanicReplyMessage.addLast(asByteArray(uuid));
        ZMsg response = majordomoClient.request(Titanic.TITANIC_REPLY_SERVICE, titanicReplyMessage, unit, value);
        ZFrame responseCode = get(response, 0);
        if (Titanic.ResponseCode.OK.equals(responseCode)) {
            return getSubMsg(response, 1);

        } else if (Titanic.ResponseCode.PENDING.equals(responseCode)) {
            return null;

        } else if (Titanic.ResponseCode.UNKNOWN.equals(responseCode)) {
            throw new IllegalStateException("Unknown UUID:" + uuid);

        } else if (Titanic.ResponseCode.ERROR.equals(responseCode)) {
            throw new IllegalStateException("Error during connect to broker");

        } else {
            throw new IllegalStateException("Unknown response code:" + responseCode + asString(get(response, 0).getData()));

        }
    }

    public void close(String uuid, TimeUnit unit, long value) {
        ZMsg titanicCloseMessage = new ZMsg();
        titanicCloseMessage.addLast(asByteArray(uuid));
        ZMsg response = majordomoClient.request(Titanic.TITANIC_CLOSE_SERVICE, titanicCloseMessage, unit, value);
        ZFrame responseCode = get(response, 0);
        if (Titanic.ResponseCode.OK.equals(responseCode)) {
            return;

        } else if (Titanic.ResponseCode.UNKNOWN.equals(responseCode)) {
            throw new IllegalStateException("Unknown UUID");

        } else if (Titanic.ResponseCode.ERROR.equals(responseCode)) {
            throw new IllegalStateException("Error during connect to broker");

        } else if (Titanic.ResponseCode.PENDING.equals(responseCode)) {
            //impossible case
            throw new IllegalStateException("Grave error");

        } else {
            throw new IllegalStateException("Unknown response code:" + responseCode);

        }
    }
}
